/*
* Copyright (C) Microsoft. All rights reserved.  
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not 
* use this file except in compliance with the License.  You may obtain a copy 
* of the License at http://www.apache.org/licenses/LICENSE-2.0  
* 
* THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
* WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
* MERCHANTABLITY OR NON-INFRINGEMENT. 
*
* See the Apache License, Version 2.0 for specific language governing 
* permissions and limitations under the License.
*
*/
#pragma once

#include <string>
#include <memory>
#include <vector>
#include <baja/common.hpp>
#include <baja/db/db_types.h>

namespace baja { namespace storage {

namespace b = baja;

// forward declarations
struct icolumn;

template<class T>
struct icolumn_typed;

// declarations
struct icolumn : public b::ibase
{
    BAJA_INTERFACE_NOTAG(icolumn);

    virtual void setId(column_id id) = 0;
    virtual void setFixed(bool fixed) = 0;
    virtual void setAutoIncrement(bool autoIncrement) = 0;
    virtual void setMaxBufferSizeInBytes(b::uint32 sizeInBytes) = 0;
    virtual void setIsBlobSize(bool isBlobSize) = 0;

    virtual column_id getId() = 0;
    virtual std::wstring getName() = 0;
    virtual column_type getType() = 0;
    virtual bool getFixed() = 0;
    virtual bool getAutoIncrement() = 0;
    virtual bool getIsBlobSize() = 0;
    virtual unsigned int getCodePage() = 0;
    virtual unsigned long getMaxBufferSizeInBytes() = 0;
};

struct icell : public b::ibase
{
    BAJA_INTERFACE_NOTAG(icell);

    virtual size_t getSize() = 0;
    virtual column_id getColumnId() = 0;
    virtual std::shared_ptr<icolumn> getColumn() = 0;
    virtual void* getBuffer() = 0;
    virtual void dump() = 0;
    virtual bool getAppendOnUpdate() = 0;
    virtual void setAppendOnUpdate(bool append) = 0;
};

template<class T>
struct icell_typed : public icell
{
    BAJA_INTERFACE_NOTAG(icell_typed);

    virtual void setValue(T value) = 0;
    virtual void setValueByMoving(T& value) = 0;
    virtual void getValueByMoving(T& value) = 0;
    virtual T getValue() = 0;
    virtual std::shared_ptr<icolumn_typed<T>> getTypedColumn() = 0;
};

template<class T>
struct icolumn_typed : public icolumn
{
    BAJA_INTERFACE_NOTAG(icolumn_typed);

    virtual std::shared_ptr<icell_typed<T>> createCell(T value) = 0;
    virtual std::shared_ptr<icell_typed<T>> createCellByMoving(T& value) = 0;
};

struct iindex_column : public b::ibase
{
    BAJA_INTERFACE_NOTAG(iindex_column);

    virtual std::shared_ptr<icolumn> getColumn() = 0;
    virtual bool getAscending() = 0;
};

struct iindex : public b::ibase
{
    BAJA_INTERFACE_NOTAG(iindex);

    virtual void addIndexColumn(std::shared_ptr<iindex_column> indexColumn) = 0;
    virtual std::wstring getName() = 0;
    virtual bool getPrimary() = 0;
    virtual bool getUnique() = 0;
    virtual std::shared_ptr<std::vector<std::shared_ptr<iindex_column>>> getIndexColumns() = 0;
};

struct itable : public b::ibase
{
    BAJA_INTERFACE_NOTAG(itable);

    virtual void setId(table_id id) = 0;
    virtual table_id getId() = 0;
    virtual std::wstring getName() = 0;
    virtual void addColumn(std::shared_ptr<icolumn> column) = 0;
    virtual std::shared_ptr<std::vector<std::shared_ptr<icolumn>>> getColumns() = 0;
    virtual void addIndex(std::shared_ptr<iindex> index) = 0;
    virtual std::shared_ptr<std::vector<std::shared_ptr<iindex>>> getIndices() = 0;
};

struct iresult_row : public b::ibase
{
    BAJA_INTERFACE_NOTAG(iresult_row);

    virtual void addCell(std::shared_ptr<icell> cell) = 0;
    virtual std::shared_ptr<std::vector<std::shared_ptr<icell>>> getCells() = 0;
};

struct iresult : public b::ibase
{
    BAJA_INTERFACE_NOTAG(iresult);

    virtual void addColumn(std::shared_ptr<icolumn> column) = 0;
    virtual std::shared_ptr<std::vector<std::shared_ptr<icolumn>>> getColumns() = 0;
    virtual void addRow(std::shared_ptr<iresult_row> row) = 0;
    virtual std::shared_ptr<std::vector<std::shared_ptr<iresult_row>>> getRows() = 0;
    virtual void dump() = 0;
};

struct iengine : public b::ibase
{
    BAJA_INTERFACE_NOTAG(iengine);

    virtual void createInstance(std::wstring workingFolderName) = 0;
    virtual void beginSession() = 0;
    virtual void createDatabase(std::wstring fileName) = 0;
    virtual void openDatabase(std::wstring fileName) = 0;
    virtual void setPageSize(unsigned int size) = 0;
    virtual void createTable(std::shared_ptr<itable> tableDefinition) = 0;
    virtual void openTable(std::shared_ptr<itable> tableDefinition) = 0;

    virtual void insert(std::shared_ptr<itable> table,
                        std::shared_ptr<std::vector<std::shared_ptr<icell>>> row) = 0;

    virtual void update(std::shared_ptr<itable> table,
                        std::shared_ptr<iindex> index,
                        std::shared_ptr<std::vector<std::shared_ptr<icell>>> criteriaRow,
                        b::uint32 criteriaCount,
                        bool assumeSingleMatch) = 0;

    virtual void read(std::shared_ptr<itable> table,
                      std::shared_ptr<iindex> index,
                      std::shared_ptr<std::vector<std::shared_ptr<icell>>> row,
                      b::uint32 criteriaCount,
                      bool assumeSingleMatch,
                      std::shared_ptr<iresult> result) = 0;

    virtual void readAll(std::shared_ptr<itable> table,
                         std::shared_ptr<iindex> index,
                         std::shared_ptr<iresult> result) = 0;

    virtual void dispose(std::shared_ptr<itable> table,
                      std::shared_ptr<iindex> index,
                      std::shared_ptr<std::vector<std::shared_ptr<icell>>> row,
                      b::uint32 criteriaCount,
                      bool assumeSingleMatch) = 0;

    virtual void disposeAll(
        std::shared_ptr<itable> table,
        std::shared_ptr<iindex> index) = 0;

	virtual void shutdown() = 0;
};

}} // namespace baja::storage